home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / PPCbwb111 / source / bwb_elx.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  36KB  |  1,231 lines

  1. /****************************************************************
  2.  
  3.         bwb_elx.c       Parse Elements of Expressions
  4.                         for Bywater BASIC Interpreter
  5.  
  6.                         Copyright (c) 1992, Ted A. Campbell
  7.  
  8.                         Bywater Software
  9.                         P. O. Box 4023
  10.                         Duke Station
  11.                         Durham, NC  27706
  12.  
  13.                         email: tcamp@acpub.duke.edu
  14.  
  15.         Copyright and Permissions Information:
  16.  
  17.         All U.S. and international copyrights are claimed by the
  18.         author. The author grants permission to use this code
  19.         and software based on it under the following conditions:
  20.         (a) in general, the code and software based upon it may be
  21.         used by individuals and by non-profit organizations; (b) it
  22.         may also be utilized by governmental agencies in any country,
  23.         with the exception of military agencies; (c) the code and/or
  24.         software based upon it may not be sold for a profit without
  25.         an explicit and specific permission from the author, except
  26.         that a minimal fee may be charged for media on which it is
  27.         copied, and for copying and handling; (d) the code must be
  28.         distributed in the form in which it has been released by the
  29.         author; and (e) the code and software based upon it may not
  30.         be used for illegal activities.
  31.  
  32. ****************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <math.h>
  39.  
  40. #include "bwbasic.h"
  41. #include "bwb_mes.h"
  42.  
  43. /***************************************************************
  44.  
  45.         FUNCTION:   exp_paren()
  46.  
  47.         DESCRIPTION:  This function interprets a parenthetical
  48.         expression, calling bwb_exp() (recursively) to resolve
  49.         the internal expression.
  50.  
  51. ***************************************************************/
  52.  
  53. int
  54. exp_paren( char *expression )
  55.    {
  56.    struct exp_ese *e;
  57.    register int c;
  58.    int s_pos;                           /* position in build buffer */
  59.    int loop;
  60.    int paren_level;
  61.  
  62.    /* find a string enclosed by parentheses */
  63.  
  64.    exp_es[ exp_esc ].pos_adv = 1;       /* start beyond open paren */
  65.    s_pos = 0;
  66.    loop = TRUE;
  67.    paren_level = 1;
  68.    exp_es[ exp_esc ].string[ 0 ] = '\0';
  69.  
  70.    while( loop == TRUE )
  71.       {
  72.  
  73.       /* check the current character */
  74.  
  75.       switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  76.          {
  77.  
  78.          case '\r':                /* these tests added v1.11 */
  79.          case '\n':
  80.          case '\0':
  81.             bwb_error( err_incomplete );
  82.             loop = FALSE;
  83.             break;
  84.  
  85.          case '(':
  86.             ++paren_level;
  87.             exp_es[ exp_esc ].string[ s_pos ]
  88.                = expression[ exp_es[ exp_esc ].pos_adv ];
  89.             ++s_pos;
  90.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  91.             break;
  92.  
  93.          case ')':
  94.  
  95.             --paren_level;
  96.             if ( paren_level == 0 )
  97.                {
  98.                loop = FALSE;
  99.                }
  100.             else
  101.                {
  102.                exp_es[ exp_esc ].string[ s_pos ]
  103.                   = expression[ exp_es[ exp_esc ].pos_adv ];
  104.                ++s_pos;
  105.                exp_es[ exp_esc ].string[ s_pos ] = '\0';
  106.                }
  107.             break;
  108.  
  109.          case '\"':                             /* embedded string constant */
  110.             ++exp_es[ exp_esc ].pos_adv;
  111.             while ( ( expression[ exp_es[ exp_esc ].pos_adv ] != '\"' )
  112.                && ( expression[ exp_es[ exp_esc ].pos_adv ] != '\0' ) )
  113.                {
  114.                exp_es[ exp_esc ].string[ s_pos ]
  115.                   = expression[ exp_es[ exp_esc ].pos_adv ];
  116.                ++s_pos;
  117.                exp_es[ exp_esc ].string[ s_pos ] = '\0';
  118.                ++exp_es[ exp_esc ].pos_adv;
  119.                }
  120.             break;
  121.  
  122.          default:
  123.             exp_es[ exp_esc ].string[ s_pos ]
  124.                = expression[ exp_es[ exp_esc ].pos_adv ];
  125.             ++s_pos;
  126.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  127.             break;
  128.          }
  129.  
  130.       /* advance the counter */
  131.  
  132.       ++exp_es[ exp_esc ].pos_adv;
  133.  
  134.       }
  135.  
  136. #if INTENSIVE_DEBUG
  137.    sprintf( bwb_ebuf, "in exp_paren() found internal string <%s>",
  138.       exp_es[ exp_esc ].string );
  139.    bwb_debug( bwb_ebuf );
  140. #endif
  141.  
  142.    /* call bwb_exp() recursively to interpret this expression */
  143.  
  144.    exp_es[ exp_esc ].rec_pos = 0;
  145.    e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
  146.           &( exp_es[ exp_esc ].rec_pos ) );
  147.  
  148.    /* assign operation and value at this level */
  149.  
  150.    exp_es[ exp_esc ].type = e->type;
  151.  
  152.    switch ( e->type )
  153.       {
  154.       case STRING:
  155.          exp_es[ exp_esc ].operation = CONST_STRING;
  156.          str_btob( exp_getsval( &( exp_es[ exp_esc ] )), exp_getsval( e ) );
  157.          break;
  158.       case INTEGER:
  159.          exp_es[ exp_esc ].operation = NUMBER;
  160.          exp_es[ exp_esc ].ival = exp_getival( e );
  161.          break;
  162.       case DOUBLE:
  163.          exp_es[ exp_esc ].operation = NUMBER;
  164.          exp_es[ exp_esc ].dval = exp_getdval( e );
  165.          break;
  166.       default:
  167.          exp_es[ exp_esc ].operation = NUMBER;
  168.          exp_es[ exp_esc ].fval = exp_getfval( e );
  169.          break;
  170.       }
  171.  
  172.    return TRUE;
  173.  
  174.    }
  175.  
  176. /***************************************************************
  177.  
  178.         FUNCTION:   exp_strconst()
  179.  
  180.         DESCRIPTION:  This function interprets a string
  181.         constant.
  182.  
  183. ***************************************************************/
  184.  
  185. int
  186. exp_strconst( char *expression )
  187.    {
  188.    int e_pos, s_pos;
  189.  
  190.    /* assign values to structure */
  191.  
  192.    exp_es[ exp_esc ].type = STRING;
  193.    exp_es[ exp_esc ].operation = CONST_STRING;
  194.  
  195.    /* set counters */
  196.  
  197.    s_pos = 0;
  198.    exp_es[ exp_esc ].pos_adv = e_pos = 1;
  199.    exp_es[ exp_esc ].string[ 0 ] = '\0';
  200.  
  201.    /* read the string up until the next double quotation mark */
  202.  
  203.    while( expression[ e_pos ] != '\"' )
  204.       {
  205.       exp_es[ exp_esc ].string[ s_pos ] = expression[ e_pos ];
  206.       ++e_pos;
  207.       ++s_pos;
  208.       ++exp_es[ exp_esc ].pos_adv;
  209.       exp_es[ exp_esc ].string[ s_pos ] = '\0';
  210.       if ( s_pos >= ( MAXSTRINGSIZE - 1 ) )
  211.          {
  212. #if PROG_ERRORS
  213.          sprintf( bwb_ebuf, "string <%s> exceeds maximum size (%d) for string constant.",
  214.             expression, MAXSTRINGSIZE );
  215.          bwb_error( bwb_ebuf );
  216. #else
  217.          bwb_error( err_overflow );
  218. #endif
  219.          return OP_NULL;
  220.          }
  221.       }
  222.  
  223.    /* now write string over to bstring */
  224.  
  225.    str_ctob( &( exp_es[ exp_esc ].sval ), exp_es[ exp_esc ].string );
  226.  
  227.    /* advance past last double quotation mark */
  228.  
  229.    ++exp_es[ exp_esc ].pos_adv;
  230.  
  231.    /* return */
  232.  
  233.    return TRUE;
  234.  
  235.    }
  236.  
  237. /***************************************************************
  238.  
  239.         FUNCTION:   exp_numconst()
  240.  
  241.         DESCRIPTION:  This function interprets a numerical
  242.         constant.
  243.  
  244. ***************************************************************/
  245.  
  246. int
  247. exp_numconst( char *expression )
  248.    {
  249.    int base;                            /* numerical base for the constant */
  250.    static struct bwb_variable mantissa; /* mantissa of floating-point number */
  251.    static int init = FALSE;        /* is mantissa variable initialized? */
  252.    int exponent;                        /* exponent for floating point number */
  253.    int man_start;                       /* starting point of mantissa */
  254.    int s_pos;                           /* position in build string */
  255.    int build_loop;
  256.    int need_pm;
  257.    int i;
  258.    double d;
  259. #if CHECK_RECURSION
  260.    static int in_use = FALSE;                   /* boolean: is function in use? */
  261.  
  262.    /* check recursion status */
  263.  
  264.    if ( in_use == TRUE )
  265.       {
  266.       sprintf( bwb_ebuf, "Recursion error in bwb_exp.c:exp_findop(): recursion violation." );
  267.       bwb_error( bwb_ebuf );
  268.       }
  269.  
  270.    /* reset recursion status indicator */
  271.  
  272.    else
  273.       {
  274.       in_use = TRUE;
  275.       }
  276. #endif
  277.  
  278.    /* initialize the variable if necessary */
  279.  
  280. #if INTENSIVE_DEBUG
  281.    strcpy( mantissa.name, "(mantissa)" );
  282. #endif
  283.  
  284.    if ( init == FALSE )
  285.       {
  286.       init = TRUE;
  287.       var_make( &mantissa, DOUBLE );
  288.       }
  289.  
  290.    /* be sure that the array_pos[ 0 ] for mantissa is set to dim_base;
  291.       this is necessary because mantissa might be used before dim_base
  292.       is set */
  293.  
  294.    mantissa.array_pos[ 0 ] = dim_base;
  295.  
  296. #if INTENSIVE_DEBUG
  297.    sprintf( bwb_ebuf, "in exp_numconst(): received <%s>, eval <%c>",
  298.       expression, expression[ 0 ] );
  299.    bwb_debug( bwb_ebuf );
  300. #endif
  301.  
  302.    need_pm = FALSE;
  303.    exp_es[ exp_esc ].ival = 0;
  304.  
  305.    /* check the first character(s) to determine numerical base
  306.       and starting point of the mantissa */
  307.  
  308.    switch( expression[ 0 ] )
  309.       {
  310.       case '-':
  311.       case '+':
  312.       case '0':
  313.       case '1':
  314.       case '2':
  315.       case '3':
  316.       case '4':
  317.       case '5':
  318.       case '6':
  319.       case '7':
  320.       case '8':
  321.       case '9':
  322.       case '.':
  323.          base = 10;                     /* decimal constant */
  324.      man_start = 0;                 /* starts at position 0 */
  325.      need_pm = FALSE;
  326.          break;
  327.       case '&':                         /* hex or octal constant */
  328.          if ( ( expression[ 1 ] == 'H' ) || ( expression[ 1 ] == 'h' ))
  329.             {
  330.             base = 16;                  /* hexadecimal constant */
  331.             man_start = 2;              /* starts at position 2 */
  332.             }
  333.          else
  334.             {
  335.             base = 8;                   /* octal constant */
  336.             if ( ( expression[ 1 ] == 'O' ) || ( expression[ 1 ] == 'o' ))
  337.                {
  338.                man_start = 2;           /* starts at position 2 */
  339.                }
  340.             else
  341.                {
  342.                man_start = 1;           /* starts at position 1 */
  343.                }
  344.             }
  345.          break;
  346.       default:
  347.  
  348. #if PROG_ERRORS
  349.          sprintf( bwb_ebuf, "expression <%s> is not a numerical constant.",
  350.             expression );
  351.          bwb_error( bwb_ebuf );
  352. #else
  353.          bwb_error( err_syntax );
  354. #endif
  355.          return OP_NULL;
  356.       }
  357.  
  358.    /* now build the mantissa according to the numerical base */
  359.  
  360.    switch( base )
  361.       {
  362.  
  363.       case 10:                          /* decimal constant */
  364.  
  365.          /* initialize counters */
  366.  
  367.          exp_es[ exp_esc ].pos_adv = man_start;
  368.          exp_es[ exp_esc ].type = INTEGER;
  369.          exp_es[ exp_esc ].string[ 0 ] = '\0';
  370.          s_pos = 0;
  371.          exponent = OP_NULL;
  372.          build_loop = TRUE;
  373.  
  374.          /* loop to build the string */
  375.  
  376.          while ( build_loop == TRUE )
  377.             {
  378.             switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  379.                {
  380.                case '-':                        /* prefixed plus or minus */
  381.                case '+':
  382.  
  383.                   /* in the first position, a plus or minus sign can
  384.                      be added to the beginning of the string to be
  385.                      scanned */
  386.  
  387.                   if ( exp_es[ exp_esc ].pos_adv == man_start )
  388.                      {
  389.                      exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  390.                      ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  391.                      ++s_pos;
  392.                      exp_es[ exp_esc ].string[ s_pos ] = '\0';
  393.                      }
  394.  
  395.                   /* but in any other position, the plus or minus sign
  396.                      must be taken as an operator and thus as terminating
  397.                      the string to be scanned */
  398.  
  399.                   else
  400.                      {
  401.                      build_loop = FALSE;
  402.                      }
  403.                   break;
  404.                case '.':                        /* note at least single precision */
  405.                   if ( exp_es[ exp_esc ].type == INTEGER )
  406.                      {
  407.                      exp_es[ exp_esc ].type = SINGLE;
  408.                      }                          /* fall through (no break) */
  409.                case '0':                        /* or ordinary digit */
  410.                case '1':
  411.                case '2':
  412.                case '3':
  413.                case '4':
  414.                case '5':
  415.                case '6':
  416.                case '7':
  417.                case '8':
  418.                case '9':
  419.                   exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  420.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  421.                   ++s_pos;
  422.                   exp_es[ exp_esc ].string[ s_pos ] = '\0';
  423.                   break;
  424.  
  425.                case 'E':                        /* exponential, single precision */
  426.                case 'e':
  427.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  428.                   exp_es[ exp_esc ].type = SINGLE;
  429.           exponent = TRUE;
  430.                   build_loop = FALSE;
  431.                   break;
  432.  
  433.  
  434.                case 'D':                        /* exponential, double precision */
  435.                case 'd':
  436.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  437.                   exp_es[ exp_esc ].type = DOUBLE;
  438.           exponent = TRUE;
  439.                   build_loop = FALSE;
  440.                   break;
  441.  
  442.                case SINGLE:                     /* single precision termination */
  443.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  444.                   exp_es[ exp_esc ].type = SINGLE;
  445.                   build_loop = FALSE;
  446.                   break;
  447.  
  448.                case DOUBLE:                     /* double precision termination */
  449.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  450.                   exp_es[ exp_esc ].type = DOUBLE;
  451.                   build_loop = FALSE;
  452.                   break;
  453.  
  454.                case INTEGER:                    /* integer precision termination */
  455.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  456.                   exp_es[ exp_esc ].type = INTEGER;
  457.                   build_loop = FALSE;
  458.                   break;
  459.  
  460.                default:                         /* anything else, terminate */
  461.                   build_loop = FALSE;
  462.                   break;
  463.                }
  464.  
  465.             }
  466.  
  467.          /* assign the value to the mantissa variable */
  468.          
  469.          sscanf( exp_es[ exp_esc ].string, "%lf", 
  470.            var_finddval( &mantissa, mantissa.array_pos ));
  471.  
  472. #if INTENSIVE_DEBUG
  473.          sprintf( bwb_ebuf, "in exp_numconst(): read mantissa, string <%s> val <%lf>",
  474.             exp_es[ exp_esc ].string, var_getdval( &mantissa ) );
  475.          bwb_debug( bwb_ebuf );
  476. #endif
  477.  
  478.          /* test if integer bounds have been exceeded */
  479.  
  480.          if ( exp_es[ exp_esc ].type == INTEGER )
  481.             {
  482.             i = (int) var_getdval( &mantissa );
  483.             d = (double) i;
  484.             if ( d != var_getdval( &mantissa ))
  485.                {
  486.                exp_es[ exp_esc ].type = DOUBLE;
  487. #if INTENSIVE_DEBUG
  488.                sprintf( bwb_ebuf, "in exp_numconst(): integer bounds violated, promote to DOUBLE" );
  489.                bwb_debug( bwb_ebuf );
  490. #endif               
  491.                }
  492.             }
  493.  
  494.          /* read the exponent if there is one */
  495.  
  496.          if ( exponent == TRUE )
  497.             {
  498.  
  499.         /* allow a plus or minus once at the beginning */
  500.  
  501.         need_pm = TRUE;
  502.  
  503.         /* initialize counters */
  504.  
  505.             exp_es[ exp_esc ].string[ 0 ] = '\0';
  506.             s_pos = 0;
  507.             build_loop = TRUE;
  508.  
  509.             /* loop to build the string */
  510.  
  511.             while ( build_loop == TRUE )
  512.                {
  513.                switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  514.                   {
  515.           case '-':                        /* prefixed plus or minus */
  516.                   case '+':
  517.  
  518.              if ( need_pm == TRUE )        /* only allow once */
  519.             {
  520.             exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  521.             ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  522.             ++s_pos;
  523.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  524.             }
  525.              else
  526.             {
  527.             build_loop = FALSE;
  528.             }
  529.              break;
  530.  
  531.           case '0':                        /* or ordinary digit */
  532.                   case '1':
  533.                   case '2':
  534.                   case '3':
  535.                   case '4':
  536.                   case '5':
  537.                   case '6':
  538.                   case '7':
  539.                   case '8':
  540.                   case '9':
  541.  
  542.                      exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  543.                      ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  544.                      ++s_pos;
  545.              exp_es[ exp_esc ].string[ s_pos ] = '\0';
  546.              need_pm = FALSE;
  547.                      break;
  548.  
  549.                   default:                         /* anything else, terminate */
  550.                      build_loop = FALSE;
  551.                      break;
  552.                   }
  553.  
  554.                }                                /* end of build loop for exponent */
  555.  
  556.             /* assign the value to the user variable */
  557.  
  558.             sscanf( exp_es[ exp_esc ].string, "%d",
  559.                &( exp_es[ exp_esc ].ival ) );
  560.  
  561. #if INTENSIVE_DEBUG
  562.         sprintf( bwb_ebuf, "in exp_numconst(): exponent is <%d>",
  563.                exp_es[ exp_esc ].ival );
  564.             bwb_debug( bwb_ebuf );
  565. #endif
  566.  
  567.             }                           /* end of exponent search */
  568.  
  569.          if ( exp_es[ exp_esc ].ival == 0 )
  570.             {
  571.             exp_es[ exp_esc ].dval = var_getdval( &mantissa );
  572.             }
  573.          else
  574.             {
  575.             exp_es[ exp_esc ].dval = var_getdval( &mantissa )
  576.                * pow( (double) 10.0, (double) exp_es[ exp_esc ].ival );
  577.             }
  578.  
  579.          exp_es[ exp_esc ].fval = (float) exp_es[ exp_esc ].dval;
  580.          exp_es[ exp_esc ].ival = (int) exp_es[ exp_esc ].dval;
  581.  
  582. #if INTENSIVE_DEBUG
  583.          sprintf( bwb_ebuf, "in exp_numconst(): val double <%lf> single <%f> int <%d>",
  584.             exp_es[ exp_esc ].dval, exp_es[ exp_esc ].fval, exp_es[ exp_esc ].ival );
  585.          bwb_debug( bwb_ebuf );
  586. #endif
  587.  
  588.          break;
  589.  
  590.       case 8:                           /* octal constant */
  591.  
  592.          /* initialize counters */
  593.  
  594.          exp_es[ exp_esc ].pos_adv = man_start;
  595.          exp_es[ exp_esc ].type = INTEGER;
  596.          exp_es[ exp_esc ].string[ 0 ] = '\0';
  597.          s_pos = 0;
  598.          exponent = OP_NULL;
  599.          build_loop = TRUE;
  600.  
  601.          /* loop to build the string */
  602.  
  603.          while ( build_loop == TRUE )
  604.             {
  605.             switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  606.                {
  607.                case '0':                        /* or ordinary digit */
  608.                case '1':
  609.                case '2':
  610.                case '3':
  611.                case '4':
  612.                case '5':
  613.                case '6':
  614.                case '7':
  615.                   exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  616.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  617.                   ++s_pos;
  618.                   exp_es[ exp_esc ].string[ s_pos ] = '\0';
  619.                   break;
  620.  
  621.                default:                         /* anything else, terminate */
  622.                   build_loop = FALSE;
  623.                   break;
  624.                }
  625.  
  626.             }
  627.  
  628.          /* now scan the string to determine the number */
  629.  
  630.          sscanf( exp_es[ exp_esc ].string, "%o",
  631.             &( exp_es[ exp_esc ].ival ));
  632.  
  633.          break;
  634.  
  635.       case 16:                          /* hexadecimal constant */
  636.  
  637.          /* initialize counters */
  638.  
  639.          exp_es[ exp_esc ].pos_adv = man_start;
  640.          exp_es[ exp_esc ].type = INTEGER;
  641.          exp_es[ exp_esc ].string[ 0 ] = '\0';
  642.          s_pos = 0;
  643.          exponent = OP_NULL;
  644.          build_loop = TRUE;
  645.  
  646.          /* loop to build the string */
  647.  
  648.          while ( build_loop == TRUE )
  649.             {
  650.             switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  651.                {
  652.                case '0':                        /* or ordinary digit */
  653.                case '1':
  654.                case '2':
  655.                case '3':
  656.                case '4':
  657.                case '5':
  658.                case '6':
  659.                case '7':
  660.                case '8':
  661.                case '9':
  662.                case 'A':
  663.                case 'a':
  664.                case 'B':
  665.                case 'b':
  666.                case 'C':
  667.                case 'c':
  668.                case 'D':
  669.                case 'd':
  670.                case 'E':
  671.                case 'e':
  672.                   exp_es[ exp_esc ].string[ s_pos ] = expression[ exp_es[ exp_esc ].pos_adv ];
  673.  
  674.                   ++exp_es[ exp_esc ].pos_adv;  /* advance to next character */
  675.                   ++s_pos;
  676.                   exp_es[ exp_esc ].string[ s_pos ] = '\0';
  677.                   break;
  678.  
  679.                default:                         /* anything else, terminate */
  680.                   build_loop = FALSE;
  681.                   break;
  682.                }
  683.  
  684.             }
  685.  
  686.          /* now scan the string to determine the number */
  687.  
  688.          sscanf( exp_es[ exp_esc ].string, "%x",
  689.             &( exp_es[ exp_esc ].ival ));
  690.  
  691.          break;
  692.       }
  693.  
  694.    /* note that the operation at this level is now a determined NUMBER */
  695.  
  696.    exp_es[ exp_esc ].operation = NUMBER;
  697.  
  698. #if INTENSIVE_DEBUG
  699.    sprintf( bwb_ebuf, "in exp_numconst(): exit level <%d> precision <%c> value <%lf>",
  700.       exp_esc, exp_es[ exp_esc ].type, exp_getdval( &( exp_es[ exp_esc ] ) ) );
  701.    bwb_debug( bwb_ebuf );
  702. #endif
  703.  
  704. #if CHECK_RECURSION
  705.    in_use = FALSE;
  706. #endif
  707.  
  708.    return TRUE;
  709.  
  710.    }
  711.  
  712. /***************************************************************
  713.  
  714.         FUNCTION:   exp_function()
  715.  
  716.         DESCRIPTION:  This function interprets a function,
  717.         calling bwb_exp() (recursively) to resolve any
  718.         arguments to the function.
  719.  
  720. ***************************************************************/
  721.  
  722. int
  723. exp_function( char *expression )
  724.    {
  725.    struct exp_ese *e;
  726.    register int c;
  727.    int s_pos;                           /* position in build buffer */
  728.    int loop;
  729.    int paren_level;
  730.    int n_args;
  731.    struct bwb_variable *v;
  732.    struct bwb_variable argv[ MAX_FARGS ];
  733.    bstring *b;
  734. #if INTENSIVE_DEBUG
  735.    char tbuf[ MAXSTRINGSIZE + 1 ];
  736.  
  737.    sprintf( bwb_ebuf, "in exp_function(): entered function, expression <%s>",
  738.       expression );
  739.    bwb_debug( bwb_ebuf );
  740. #endif
  741.  
  742.    /* assign pointers to argument stack */
  743.  
  744.    /* get the function name */
  745.  
  746.    exp_getvfname( expression, exp_es[ exp_esc ].string );
  747.  
  748. #if INTENSIVE_DEBUG
  749.    sprintf( bwb_ebuf, "in exp_function(): name is <%s>.",
  750.       exp_es[ exp_esc ].string );
  751.    bwb_debug( bwb_ebuf );
  752. #endif
  753.  
  754.    /* now find the function itself */
  755.  
  756.    exp_es[ exp_esc ].function = fnc_find( exp_es[ exp_esc ].string );
  757.  
  758.    /* check to see if it is valid */
  759.  
  760.    if ( exp_es[ exp_esc ].function == NULL )
  761.       {
  762. #if PROG_ERRORS
  763.       sprintf( bwb_ebuf, "Failed to find function <%s>.",
  764.          exp_es[ exp_esc ].string );
  765.       bwb_error( bwb_ebuf );
  766. #else
  767.       bwb_error( err_uf  );
  768. #endif
  769.       return OP_ERROR;
  770.       }
  771.  
  772.    /* note that this level is a function */
  773.  
  774.    exp_es[ exp_esc ].operation = FUNCTION;
  775.    exp_es[ exp_esc ].pos_adv = strlen( exp_es[ exp_esc ].string );
  776.  
  777.    /* check for begin parenthesis */
  778.  
  779.    loop = TRUE;
  780.    while( loop == TRUE )
  781.       {
  782.       switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  783.          {
  784.  
  785.          case ' ':                              /* whitespace */
  786.          case '\t':
  787.             ++exp_es[ exp_esc ].pos_adv;        /* advance */
  788.             break;
  789.  
  790.          case '(':                              /* begin paren */
  791.  
  792. #if INTENSIVE_DEBUG
  793.             sprintf( bwb_ebuf, "in exp_function(): found begin parenthesis." );
  794.             bwb_debug( bwb_ebuf );
  795. #endif
  796.  
  797.             ++exp_es[ exp_esc ].pos_adv;        /* advance beyond it */
  798.             paren_level = 1;                    /* set paren_level */
  799.             loop = FALSE;                       /* and break out */
  800.             break;
  801.  
  802.          default:                               /* anything else */
  803.             loop = FALSE;
  804.             paren_level = 0;                    /* do not look for arguments */
  805.             break;
  806.          }
  807.       }
  808.  
  809.    /* find arguments within parentheses */
  810.    /* for each argument, find a string ending with ',' or with end parenthesis */
  811.  
  812.    n_args = 0;
  813.    s_pos = 0;
  814.    exp_es[ exp_esc ].string[ 0 ] = '\0';
  815.  
  816.    while( paren_level > 0 )
  817.       {
  818.  
  819.       /* check the current character */
  820.  
  821.       switch( expression[ exp_es[ exp_esc ].pos_adv ] )
  822.          {
  823.  
  824.          case ',':                      /* end of an argument */
  825.  
  826.             if ( paren_level == 1 )     /* ignore ',' within parentheses */
  827.                {
  828.  
  829.                /* call bwb_exp() recursively to resolve the argument */
  830.  
  831.                if ( exp_validarg( exp_es[ exp_esc ].string ) == TRUE )
  832.                   {
  833. #if INTENSIVE_DEBUG
  834.           sprintf( bwb_ebuf,
  835.              "in exp_function(): valid argument (not last)." );
  836.                   bwb_debug( bwb_ebuf );
  837. #endif
  838.  
  839.                   exp_es[ exp_esc ].rec_pos = 0;
  840.                   e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
  841.                      &( exp_es[ exp_esc ].rec_pos ) );
  842.  
  843.                   /* assign operation and value at this level */
  844.  
  845.                   var_make( &( argv[ n_args ] ), e->type );
  846.  
  847.                   switch( argv[ n_args ].type )
  848.                      {
  849.                      case DOUBLE:
  850.                         * var_finddval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  851.                             = exp_getdval( e );
  852.                         break;
  853.                      case SINGLE:
  854.                         * var_findfval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  855.                             = exp_getfval( e );
  856.                         break;
  857.                      case INTEGER:
  858.                         * var_findival( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  859.                             = exp_getival( e );
  860.                         break;
  861.                      case STRING:
  862.                         str_btob( var_findsval( &( argv[ n_args ] ),
  863.                            argv[ n_args ].array_pos ), exp_getsval( e ) );
  864.                         break;
  865.                      }
  866.  
  867.                   ++n_args;                /* increment number of arguments */
  868.  
  869.                   }
  870.  
  871.                s_pos = 0;               /* reset counter */
  872.                exp_es[ exp_esc ].string[ 0 ] = '\0';
  873.                }
  874.  
  875.             else
  876.                {
  877.                exp_es[ exp_esc ].string[ s_pos ]
  878.                   = expression[ exp_es[ exp_esc ].pos_adv ];
  879.                ++s_pos;
  880.                exp_es[ exp_esc ].string[ s_pos ] = '\0';
  881.                }
  882.             break;
  883.  
  884.          case '(':
  885.             ++paren_level;
  886.             exp_es[ exp_esc ].string[ s_pos ]
  887.                = expression[ exp_es[ exp_esc ].pos_adv ];
  888.             ++s_pos;
  889.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  890.             break;
  891.  
  892.          case ')':
  893.             --paren_level;
  894.  
  895. #if INTENSIVE_DEBUG
  896.             sprintf( bwb_ebuf,
  897.                "in exp_function(): hit close parenthesis." );
  898.             bwb_debug( bwb_ebuf );
  899. #endif
  900.  
  901.             if ( paren_level == 0 )
  902.                {
  903.  
  904. #if INTENSIVE_DEBUG
  905.                sprintf( bwb_ebuf,
  906.                   "in exp_function(): paren level 0." );
  907.                bwb_debug( bwb_ebuf );
  908. #endif
  909.  
  910.                /* call bwb_exp() recursively to resolve the argument */
  911.  
  912.                if ( exp_validarg( exp_es[ exp_esc ].string ) == TRUE )
  913.                   {
  914. #if INTENSIVE_DEBUG
  915.           sprintf( bwb_ebuf,
  916.              "in exp_function(): valid argument (last)." );
  917.           bwb_debug( bwb_ebuf );
  918. #endif
  919.  
  920.                   exp_es[ exp_esc ].rec_pos = 0;
  921.                   e = bwb_exp( exp_es[ exp_esc ].string, FALSE,
  922.                      &( exp_es[ exp_esc ].rec_pos ) );
  923.  
  924. #if INTENSIVE_DEBUG
  925.           sprintf( bwb_ebuf,
  926.              "in exp_function(): return from bwb_exp(), last arg, type <%c> op <%d>",
  927.              e->type, e->operation );
  928.           bwb_debug( bwb_ebuf );
  929. #endif
  930.  
  931.                   /* assign operation and value at this level */
  932.  
  933.                   var_make( &( argv[ n_args ] ), e->type );
  934.  
  935.                   switch( argv[ n_args ].type )
  936.                      {
  937.                      case DOUBLE:
  938.                         * var_finddval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  939.                             = exp_getdval( e );
  940.                         break;
  941.                      case SINGLE:
  942.                         * var_findfval( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  943.                             = exp_getfval( e );
  944.                         break;
  945.                      case INTEGER:
  946.                         * var_findival( &( argv[ n_args ] ), argv[ n_args ].array_pos )
  947.                             = exp_getival( e );
  948.                         break;
  949.                      case STRING:
  950.                         str_btob( var_findsval( &( argv[ n_args ] ),
  951.                            argv[ n_args ].array_pos ), exp_getsval( e ) );
  952.                         break;
  953.                      }
  954.  
  955.                   ++n_args;                /* increment number of arguments */
  956.  
  957.                   }
  958.  
  959.                s_pos = 0;               /* reset counter */
  960.                exp_es[ exp_esc ].string[ 0 ] = '\0';
  961.                }
  962.  
  963.             else
  964.                {
  965.                exp_es[ exp_esc ].string[ s_pos ]
  966.                   = expression[ exp_es[ exp_esc ].pos_adv ];
  967.                ++s_pos;
  968.                exp_es[ exp_esc ].string[ s_pos ] = '\0';
  969.                }
  970.             break;
  971.  
  972.          case '\"':                             /* embedded string constant */
  973.  
  974.             /* add the initial quotation mark */
  975.  
  976.             exp_es[ exp_esc ].string[ s_pos ]
  977.                = expression[ exp_es[ exp_esc ].pos_adv ];
  978.             ++s_pos;
  979.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  980.             ++exp_es[ exp_esc ].pos_adv;
  981.  
  982.             /* add intervening characters */
  983.  
  984.             while ( ( expression[ exp_es[ exp_esc ].pos_adv ] != '\"' )
  985.                && ( expression[ exp_es[ exp_esc ].pos_adv ] != '\0' ) )
  986.                {
  987.                exp_es[ exp_esc ].string[ s_pos ]
  988.                   = expression[ exp_es[ exp_esc ].pos_adv ];
  989.                ++s_pos;
  990.                exp_es[ exp_esc ].string[ s_pos ] = '\0';
  991.                ++exp_es[ exp_esc ].pos_adv;
  992.                }
  993.  
  994.             /* add the concluding quotation mark */
  995.  
  996.             exp_es[ exp_esc ].string[ s_pos ]
  997.                = expression[ exp_es[ exp_esc ].pos_adv ];
  998.             ++s_pos;
  999.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  1000.             /* the following bracketed out 14 July 1992; since this counter */
  1001.             /* incremented at the end of the switch statement, this may */
  1002.             /* increment it past the next character needed */
  1003.             /* ++exp_es[ exp_esc ].pos_adv; */
  1004.             break;
  1005.  
  1006.          default:
  1007.             exp_es[ exp_esc ].string[ s_pos ]
  1008.                = expression[ exp_es[ exp_esc ].pos_adv ];
  1009.             ++s_pos;
  1010.             exp_es[ exp_esc ].string[ s_pos ] = '\0';
  1011. #if INTENSIVE_DEBUG
  1012.             sprintf( bwb_ebuf, "in exp_function(): new char <%d>=<%c>",
  1013.                expression[ exp_es[ exp_esc ].pos_adv ],
  1014.                expression[ exp_es[ exp_esc ].pos_adv ] );
  1015.             bwb_debug( bwb_ebuf );
  1016.             sprintf( bwb_ebuf, "in exp_function(): building <%s>.",
  1017.                exp_es[ exp_esc ].string );
  1018.             bwb_debug( bwb_ebuf );
  1019. #endif
  1020.             break;
  1021.          }
  1022.  
  1023.       /* advance the counter */
  1024.  
  1025.       ++exp_es[ exp_esc ].pos_adv;
  1026.  
  1027.       }
  1028.  
  1029. #if INTENSIVE_DEBUG
  1030.    sprintf( bwb_ebuf, "in exp_function(): ready to call function vector" );
  1031.    bwb_debug( bwb_ebuf );
  1032. #endif
  1033.  
  1034.    /* call the function vector */
  1035.  
  1036.    if ( exp_es[ exp_esc ].function->ufnc != NULL )
  1037.       {
  1038. #if INTENSIVE_DEBUG
  1039.       sprintf( bwb_ebuf, "in exp_function(): calling fnc_intufnc()" );
  1040.       bwb_debug( bwb_ebuf );
  1041. #endif
  1042.       v = fnc_intufnc( n_args, &( argv[ 0 ] ), exp_es[ exp_esc ].function );
  1043.       }
  1044.    else
  1045.       {
  1046. #if INTENSIVE_DEBUG
  1047.       sprintf( bwb_ebuf, "in exp_function(): calling preset function" );
  1048.       bwb_debug( bwb_ebuf );
  1049. #endif
  1050.       v = exp_es[ exp_esc ].function->vector ( n_args, &( argv[ 0 ] ) );
  1051.       }
  1052.  
  1053. #if INTENSIVE_DEBUG
  1054.    sprintf( bwb_ebuf, "in exp_function(): return from function vector, type <%c>",
  1055.       v->type );
  1056.    bwb_debug( bwb_ebuf );
  1057. #endif
  1058.  
  1059.    /* assign the value at this level */
  1060.  
  1061.    exp_es[ exp_esc ].type = (char) v->type;
  1062.    
  1063.    switch( v->type )
  1064.       {
  1065.       case STRING:
  1066.          exp_es[ exp_esc ].operation = CONST_STRING;
  1067.  
  1068. #if INTENSIVE_DEBUG
  1069.          sprintf( bwb_ebuf, "in exp_function(): ready to assign STRING" );
  1070.          bwb_debug( bwb_ebuf );
  1071. #endif
  1072.  
  1073.          b = var_findsval( v, v->array_pos );
  1074.          str_btob( exp_getsval( &( exp_es[ exp_esc ] )), b );
  1075.  
  1076. #if INTENSIVE_DEBUG
  1077.          str_btoc( tbuf, b );
  1078.          sprintf( bwb_ebuf, "in exp_function(): string assigned <%s>", tbuf );
  1079.          bwb_debug( bwb_ebuf );
  1080. #endif
  1081.  
  1082.          break;
  1083.  
  1084.       case DOUBLE:
  1085.          exp_es[ exp_esc ].operation = NUMBER;
  1086.          exp_es[ exp_esc ].dval = var_getdval( v );
  1087.          break;
  1088.       case INTEGER:
  1089.          exp_es[ exp_esc ].operation = NUMBER;
  1090.          exp_es[ exp_esc ].ival = var_getival( v );
  1091.          break;
  1092.       default:
  1093.          exp_es[ exp_esc ].operation = NUMBER;
  1094.          exp_es[ exp_esc ].fval = var_getfval( v );
  1095.          break;
  1096.       }
  1097.  
  1098. #if INTENSIVE_DEBUG
  1099.    sprintf( bwb_ebuf, "in exp_function(): end of function" );
  1100.    bwb_debug( bwb_ebuf );
  1101. #endif
  1102.  
  1103.    /* return */
  1104.  
  1105.    return TRUE;
  1106.  
  1107.    }
  1108.  
  1109. /***************************************************************
  1110.  
  1111.         FUNCTION:   exp_variable()
  1112.  
  1113.         DESCRIPTION:  This function interprets a variable.
  1114.  
  1115. ***************************************************************/
  1116.  
  1117. int
  1118. exp_variable( char *expression )
  1119.    {
  1120.    int pos;
  1121.    int *pp;
  1122.    int n_params;
  1123.    register int n;
  1124.    struct bwb_variable *v;
  1125.    bstring *b;
  1126.    int p;
  1127.  
  1128. #if INTENSIVE_DEBUG
  1129.    sprintf( bwb_ebuf, "in exp_variable(): entered function." );
  1130.    bwb_debug( bwb_ebuf );
  1131. #endif
  1132.  
  1133.    /* get the variable name */
  1134.  
  1135.    exp_getvfname( expression, exp_es[ exp_esc ].string );
  1136.  
  1137.    /* now find the variable itself */
  1138.  
  1139.    v = exp_es[ exp_esc ].xvar = var_find( exp_es[ exp_esc ].string );
  1140.  
  1141. #if INTENSIVE_DEBUG
  1142.    sprintf( bwb_ebuf, "in exp_variable(): level <%d>, found variable name <%s>",
  1143.       exp_esc, exp_es[ exp_esc ].xvar->name );
  1144.    bwb_debug( bwb_ebuf );
  1145. #endif
  1146.  
  1147.    /* note that this level is a variable */
  1148.  
  1149.    exp_es[ exp_esc ].operation = VARIABLE;
  1150.  
  1151.    /* read subscripts */
  1152.  
  1153.    pos = strlen( exp_es[ exp_esc ].string );
  1154.    if ( ( v->dimensions == 1 ) && ( v->array_sizes[ 0 ] == 1 ))
  1155.       {
  1156. #if INTENSIVE_DEBUG
  1157.       sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has 1 dimension",
  1158.          exp_es[ exp_esc ].xvar->name );
  1159.       bwb_debug( bwb_ebuf );
  1160. #endif
  1161.       pos = strlen( v->name );
  1162.       n_params = 1;
  1163.       pp = &p;
  1164.       pp[ 0 ] = dim_base;
  1165.       }
  1166.    else
  1167.       {
  1168. #if INTENSIVE_DEBUG
  1169.       sprintf( bwb_ebuf, "in exp_variable(): variable <%s> has > 1 dimensions",
  1170.          exp_es[ exp_esc ].xvar->name );
  1171.       bwb_debug( bwb_ebuf );
  1172. #endif
  1173.       dim_getparams( expression, &pos, &n_params, &pp );
  1174.       }
  1175.  
  1176.    exp_es[ exp_esc ].pos_adv = pos;
  1177.    for ( n = 0; n < v->dimensions; ++n )
  1178.       {
  1179.       exp_es[ exp_esc ].array_pos[ n ] = v->array_pos[ n ] = pp[ n ];
  1180.       }
  1181.  
  1182. #if INTENSIVE_DEBUG
  1183.    for ( n = 0; n < v->dimensions; ++ n )
  1184.       {
  1185.       sprintf( bwb_ebuf, "in exp_variable(): var <%s> array_pos element <%d> is <%d>.",
  1186.          v->name, n, v->array_pos[ n ] );
  1187.       bwb_debug( bwb_ebuf );
  1188.       }
  1189. #endif
  1190.  
  1191.    /* assign the type and value at this level */
  1192.  
  1193.    exp_es[ exp_esc ].type = (char) v->type;
  1194.    
  1195.    switch( v->type )
  1196.       {
  1197.       case STRING:
  1198.          b = var_findsval( v, v->array_pos );
  1199. #if TEST_BSTRING
  1200.          sprintf( bwb_ebuf, "in exp_variable(): b string name is <%s>",
  1201.             b->name );
  1202.          bwb_debug( bwb_ebuf );
  1203. #endif
  1204.          exp_es[ exp_esc ].sval.length = b->length;
  1205.          exp_es[ exp_esc ].sval.buffer = b->buffer;
  1206.          break;
  1207.       case DOUBLE:
  1208.          exp_es[ exp_esc ].dval = var_getdval( v );
  1209.          break;
  1210.       case INTEGER:
  1211.          exp_es[ exp_esc ].ival = var_getival( v );
  1212.          break;
  1213.       default:
  1214.          exp_es[ exp_esc ].fval = var_getfval( v );
  1215.          break;
  1216.       }
  1217.  
  1218. #if INTENSIVE_DEBUG
  1219.    sprintf( bwb_ebuf, "in exp_variable(): exit, name <%s>, level <%d>, op <%d>",
  1220.       v->name, exp_esc, exp_es[ exp_esc ].operation  );
  1221.    bwb_debug( bwb_ebuf );
  1222. #endif
  1223.  
  1224.    /* return */
  1225.  
  1226.    return TRUE;
  1227.  
  1228.    }
  1229.  
  1230.  
  1231.